perm filename TCPPAR.MAC[IP,SYS] blob sn#680225 filedate 1982-10-14 generic text, type T, neo UTF8
;CWL:<403-TCP>TCPPAR.MAC.40303 29-Apr-82  7:42:16, Edit by CLYNN
; Add Max Segment Length option, TRLAK, TRLWN, options, etc
;<403-TCP>TCPPAR.MAC.40301 29-Jan-82 15:06:18, Edit by CLYNN
; Updated for TCP release 3
; Move JSYS-related definitions to MONSYM (via MONSYM.D4I)
; Add definition of PTVT parallel to that in TTTVDV.MAC for use by BG

	UNIVER	TCPPAR
	SUBTTL	TCP Parameters, William W. Plummer, 2Mar79
	SEARCH	INPAR,IMPPAR,PROLOG,MONSYM,MACSYM

SYN INBUG,TCPBUG		; Use Internet bug macro

; Make sure MNET switch = 0, if not defined
IFNDEF MNET,<MNET==0>

; Check consistency of IMPPAR with TCPPAR:

IF1 <	IFDEF .TCPFM,<
	  IFN .TCPFM-6,<PRINTX % .TCPFM defined wrong in IMPPAR
			.TCPFM==6
	  >
	>
	IFNDEF .TCPFM,<;;;PRINTX % .TCPFM not defined in IMPPAR
			.TCPFM==6
	>
>


; TCP Parameters:

MAXSEQ==1←↑D32		;STG	; 32 bit sequence numbers
SEQMSK==MAXSEQ-1		; Mask for doing mod MAXSEQ by AND op.
DEFINE MODSEQ(A)<TLZ A,(-MAXSEQ)>

CYCTIM==↑D<2*60*60>	;STG	; Network cycle time in seconds
;MLIFET==30*60			; Assumed message lifetime in seconds
SNSTEP==MAXSEQ/CYCTIM		; A second's worth of sequence numbers
;SNMARG==MLIFET*SNSTEP/2	; Half width of forbidden zone
; TCP Header (indexed by TPKT):

.P==0
DEFSTR(PSP,\<.P>,15,16)		; PACKET.SOURCE.PORT
DEFSTR(PDP,\<.P>,31,16)		; PACKET.DESTINATION.PORT
.P==.P+1
DEFSTR(PSEQ,\<.P>,31,32)	; PACKET.SEQUENCE
.P==.P+1
DEFSTR(PACKS,\<.P>,31,32)	; PACKET.ACK.SEQUENCE
.P==.P+1
DEFSTR(PCTL,\<.P>,35,36)	; Word containing control flags
; Substructures and overlays for above:
  DEFSTR(PTDO,\<.P>,3,4)	; PACKET.TCP.DATAOFFSET ( 32-BIT UNITS)
  ; 4 Unused bits
  DEFSTR(PTCTL,\<.P>,15,8)	; PACKET.TCP.CONTROLS
    ; 2 Unsed bits
    DEFSTR(PURG,\<.P>,10,1)	; PACKET.CONTROL.URGENT
    DEFSTR(PACK,\<.P>,11,1)	; PACKET.CONTROL.ACK
    DEFSTR(PEOL,\<.P>,12,1)	; PACKET.CONTROL.EOL
    DEFSTR(PRST,\<.P>,13,1)	; PACKET.CONTROL.RST
    DEFSTR(PSYN,\<.P>,14,1)	; PACKET.CONTROL.SYN
    DEFSTR(PFIN,\<.P>,15,1)	; PACKET.CONTROL.FIN
DEFSTR(PWNDO,\<.P>,31,16)	; PACKET.WINDOW
.P==.P+1
DEFSTR(PTCKS,\<.P>,15,16)	; PACKET.CHECKSUM
DEFSTR(PURGP,\<.P>,31,16)	; PACKET.URGENT.POINTER
.P==.P+1

MINTHS==4*.P			; Minimum TCP header size (bytes)

; TCP Options (if any) are here:

;MINTOS==10			; Minimum # Option bytes to cope with
MAXTOS==<.RTJST(-1,PTDO)*4-MINTHS>	; Maximum # Option bytes possible

; Derive some useful numbers from the above:

TCPNPW==PKTELI+.RTJST(-1,PIDO)+.RTJST(-1,PTDO)+<<<1←↑D<WID(PIPL)-WID(PIFO)>>+3>/4>
;	Local info + IP + TCP + fragment =  Minimum TCP packet, Words

;MAXDSZ==4*<<M2+3>/4>-<4*<<MINIHS+3>/4>>-<4*<<MINTHS+3>/4>>
				; Max. number of TCP data bytes
;MINPLN==4*<PKTELI+17+17>	; Maximum packet header length
;MINDSZ==MAXDSZ-<4*<<MINIOS+3>/4>>-<4*<<MINTOS+3>/4>>
				; Min. number of bytes per Pkt estimated
;MINPSZ==PKTELI+<<MINIHS+3>/4>+<<MINIOS+3>/4>+<<MINTHS+3>/4>+<<MINTOS+3>/4>

; Options: Two cases.

; Case 1: A single byte of option code

; ENDOPT is and must be 0.  This marks the end of the option list.
; NOPOPT is and must be 1.  This is one byte long and has no purpose.

; Case 2: General form of options is 1 byte of "kind", 1 byte of total
; length, and N-2 bytes of data, where N is read from the length byte.

; All options are included under the appropriate checksum.


; END	End of options		ENDOPT
; NOP	Filler			NOPOPT
; MSL	Maximul Segment Length	MSLOPT,4,len,gth
; LBL	Packet Label		LBLOPT,4,seg,id
; RBS	Receive Buffer Size	RBSOPT,4,bfr,lth
; LTS	Local Timestamp		LTSOPT,6,t,i,m,e


; General TCP Option generation macro


DEFINE TCPOPTS (USER,RECV,ECHO)<
  OPTION(I,END,,↑D0,↑D1,USER,RECV,ECHO)
  OPTION(I,NOP,,↑D1,↑D1,USER,RECV,ECHO)
  OPTION(T,MSL,,↑D2,↑D4,USER,RECV,ECHO)
  OPTION(T,LBL,,↑D33,↑D4,USER,RECV,ECHO)
; OPTION(T,RBS,,↑D37,↑D4,USER,RECV,ECHO)
; OPTION(T,LTS,,↑D132,↑D6,USER,RECV,ECHO)
> ; End of DEFINE TCPOPTS



; Define Option Names

DEFINE OPTION(TYPE,NAME,COPY,NUMBER,LENGTH,USER,RECV,ECHO)<
IFDIF <COPY>,<C>,<	NAME'OPT==NUMBER	>
IFIDN <COPY>,<C>,<	NAME'OPT==CPYOPT+NUMBER	>
>

TCPOPTS
; TCB (internal connection block) structure:

TCBQ==<.T==0>				; TCB Queue (TCBH, DeadQ, etc)

TCBLCK==<.T==.T+QSZ>			; TCB.LOCK

.T==.T+LOCKSZ
DEFSTR(TOWNR,\<.T>,17,18)		; TCB.OWNER	(job #)
DEFSTR(TJCN,\<.T>,35,18)		; TCB.JCN	(n of JCNTCB+n)

.T=.T+1
DEFSTR(TFH,\<.T>,35,36)			; TCB.FH
DEFSTR(TFHC,\<.T>,6,3)			; TCB.FH.NET-CLASS
					; TCB.FH.NET	(0 => TWLDN=1)
.T=.T+1					; TCB.FH.TCP	(0 => TWLDT=1)
DEFSTR(TLH,\<.T>,35,36)			; TCB.LH

.T=.T+1
DEFSTR(TFP,\<.T>,35,36)			; TCB.FP  ***	(0 => TWLDP=1)

.T=.T+1
DEFSTR(TLP,\<.T>,35,36)			; TCB.LP  *** only 16 bits

.T=.T+1
;DEFSTR(TFLAG,\<.T>,20,21)		; TCB.Flags
  ; Substructures for the above:
  DEFSTR(TERR,\<.T>,7,8)		; TCB.ERROR
  DEFSTR(TWLDN,\<.T>,8,1)		; OPEN with Net wild
  DEFSTR(TWLDT,\<.T>,9,1)		; OPEN with TCP wild
  DEFSTR(TWLDP,\<.T>,10,1)		; OPEN with Port wild
  DEFSTR(TSFP,\<.T>,11,1)		; TCB.SEND.FORCE-PACKET
  DEFSTR(TSEP,\<.T>,12,1)		; TCB.SEND.ENCOURAGE-PACKET
; DEFSTR(TRPB,\<.T>,13,1)		; TCB.RECV.PARTIAL-BUFFER
  DEFSTR(TRPP,\<.T>,14,1)		; TCB.RECV.PARITAL-PACKET
  DEFSTR(TSCR,\<.T>,15,1)		; TCB.SECURE-CONNECTION
  DEFSTR(TTVT,\<.T>,16,1)		; TCB.TCP-Virtual-terminal
  DEFSTR(TSAP,\<.T>,17,1)
  DEFSTR(TERRT,\<.T>,20,1)		; TCB.ERROR.TRACE

DEFSTR(TSTAT,\<.T>,35,15)		; TCB.STATE
  ; Overlays for above
  DEFSTR(TRSYN,\<.T>,23,3)		; TCB.STATE.RECV-SYNC
  DEFSTR(TSSYN,\<.T>,26,3)		; TCB.STATE.SEND-SYNC
	; State codes for connections (in TRSYN and TSSYN):
	SYNABL==4			; SYNCHABLE: Activated by user call
	SYNSNT==<SYNRCV==5>		; SYN sent or received
	SYNCED==7			; SYN acked
	FINSNT==<FINRCV==2>		; FIN sent or received but not ACKd
	NOTSYN==0			; Connection fully closed or not open
  DEFSTR(TSUOP,\<.T>,27,1)		; TCB.STATE.USER-OPEN
  DEFSTR(TSOPN,\<.T>,28,1)		; TCB.STATE.SAID-OPEN
  DEFSTR(TSPRS,\<.T>,29,1)		; TCB.STATE.PERSISTENT
  DEFSTR(TSABT,\<.T>,30,1)		; TCB.STATE.ABORT
  DEFSTR(TSSV,\<.T>,31,1)		; TCB.STATE.SEQUENCE-VALID
  ; 2 Unused bits
  DEFSTR(TSURG,\<.T>,34,1)		; TCB.SEND.URGENT-MODE
  DEFSTR(TRURG,\<.T>,35,1)		; TCB.RECV.URGENT-MODE

; Send variables

.T=.T+1
DEFSTR(TSLFT,\<.T>,35,36)		; TCB.SEND.LEFT
.T=.T+1
DEFSTR(TSSEQ,\<.T>,35,36)		; TCB.SEND.SEQUENCE
.T=.T+1
DEFSTR(TSURP,\<.T>,35,36)		; TCB.SEND.URGENT-POINTER
.T=.T+1
DEFSTR(TSWND,\<.T>,17,18)		; TCB.SEND.WINDOW
DEFSTR(TSCB,\<.T>,35,18)		; TCB.SEND.CURRENT-BUFFER
.T=.T+1
DEFSTR(TSTO,\<.T>,35,36)		; TCB.SEND.TIME-OUT

TCBSBQ==<.T=.T+1>			; TCB.SEND.BUFFER-QUEUE
TCBRXQ==<.T=.T+QSZ>			; TCB.SEND.REXMIT-QUEUE

; Recv variables

.T==.T+QSZ
DEFSTR(TRIS,\<.T>,35,36)		; TCB.RECV.INITIAL-SEQUENCE
.T=.T+1
DEFSTR(TRLFT,\<.T>,35,36)		; TCB.RECV.LEFT
.T=.T+1
DEFSTR(TRURP,\<.T>,35,36)		; TCB.RECV.URGENT-POINTER
.T=.T+1
DEFSTR(TRWND,\<.T>,17,18)		; TCB.RECV.WINDOW
DEFSTR(TRCB,\<.T>,35,18)		; TCB.RECV.CURRENT-BUFFER
.T=.T+1
DEFSTR(TRCBY,\<.T>,35,36)		; TCB.RECV.CURRENT-BYTE
.T=.T+1
DEFSTR(TRBS,\<.T>,35,36)		; TCB.RECV.BUFFER-SPACE

TCBRBQ==<.T=.T+1>			; TCB.RECV.BUFFER-QUEUE
TCBRPQ==<.T=.T+QSZ>			; TCB.RECV.PACKET-QUEUE

; PSI variables

TCBPIC==<.T=.T+QSZ>			; TCB.PSI-CHANNELS
DEFSTR(TPSIC,TCBPIC,35,36)		; All PSI channels
  ; Overlays for above:
  DEFSTR(TPICU,TCBPIC,5,6)		; URGENT DATA ARRIVED
  DEFSTR(TPICR,TCBPIC,11,6)		; RECV DONE
  DEFSTR(TPICS,TCBPIC,17,6)		; SEND DONE
  DEFSTR(TPICE,TCBPIC,23,6)		; ERROR
  DEFSTR(TPICX,TCBPIC,29,6)		; STATE CHANGE
  DEFSTR(TPICA,TCBPIC,35,6)		; EOL ACK
; Following must have same order as above
TCBPIF==.T+1				; TCB.PSI-FORKS
DEFSTR(TPIFU,TCBPIF+0,17,18)		; URGENT DATA ARRIVED
DEFSTR(TPIFR,TCBPIF+0,35,18)		; RECV DONE
DEFSTR(TPIFS,TCBPIF+1,17,18)		; SEND DONE
DEFSTR(TPIFE,TCBPIF+1,35,18)		; ERROR
DEFSTR(TPIFX,TCBPIF+2,17,18)		; STATE CHANGE
DEFSTR(TPIFA,TCBPIF+2,35,18)		; EOL ACK

.T==TCBPIF+3
DEFSTR(TOPNF,\<.T>,8,9)			; TCB.OPEN.WAIT FLAG INDEX
DEFSTR(TERRF,\<.T>,17,9)		; TCB.ERROR.FLAG index
DEFSTR(TOFRK,\<.T>,35,18)		; TCB.OWNING-FORK

; Retransmission variables

.T=.T+1
DEFSTR(TSMRT,\<.T>,35,36)		; TCB.SMOOTHED-ROUND-TRIP (or)
DEFSTR(TMNRT,\<.T>,35,36)		; TCB.MIN-ROUND-TRIP
.T=.T+1
DEFSTR(TMXRT,\<.T>,35,36)		; TCB.MAX-ROUND-TRIP
.T=.T+1
DEFSTR(TRXI,\<.T>,35,36)		; TCB.RETRANSMIT-INTERVAL
.T=.T+1
DEFSTR(TRXP,\<.T>,35,36)		; TCB.Retransmission.Parameters
  ;Substructures of the above:
  DEFSTR(TRXPN,\<.T>,8,9)		; Numberator of backoff fraction
  DEFSTR(TRXPD,\<.T>,17,9)		; Denominator thereof
  DEFSTR(TRXPI,\<.T>,35,18)		; Initial interval

; Queues and wakeup times for various processes:

TCBQRA==<.T=.T+1>			; Reassembler queue
TCBTRA==<.T=.T+QSZ>			; When RA needed

TCBQPZ==<.T=.T+1>			; Packetizer
TCBTPZ==<.T=.T+QSZ>

TCBQRX==<.T=.T+1>			; Retransmitter
TCBTRX==<.T=.T+QSZ>

TCBQDG==<.T=.T+1>			; Delay Actions
TCBTDG==<.T=.T+QSZ>

.T==.T+1
DEFSTR(TIFDF,\<.T>,0,1)			; IP Don't-Fragment flag
DEFSTR(TTTL,\<.T>,8,8)			; IP Time-to-live
; 1 Unused bit
DEFSTR(TTOS,\<.T>,17,8)			; IP Type-of-service
DEFSTR(TABTFX,\<.T>,35,18)		; Forkx of ABORTER

.T=.T+1
DEFSTR(TSLVN,\<.T>,17,18)		; Next Security level
DEFSTR(TSLVC,\<.T>,35,18)		; Current Security Level

.T=.T+1
; 2 bits really unused
DEFSTR(TOPFP,\<.T>,17,18)		; Foreign port at open
DEFSTR(TNUFM,\<.T>,18,1)		; OPENed with new formats
; 8 unused bits
DEFSTR(TVTL,\<.T>,35,9)			; Virtual terminal line number

.T=.T+1
DEFSTR(TOPFH,\<.T>,35,36)		; TCB.OPEN-FH

.T=.T+1
DEFSTR(TOPLH,\<.T>,35,36)		; TCB.OPEN-LH

.T=.T+1
DEFSTR(TSBYT,\<.T>,35,36)		; Bytes left to send

.T=.T+1
DEFSTR(TRLAK,\<.T>,35,36)		; Seq # of last PACKS sent

.T=.T+1
DEFSTR(TRLWN,\<.T>,35,36)		; Seq # of last PWNDO sent or -1

.T=.T+1
DEFSTR(TSMXB,\<.T>,35,36)		; Max send rate

.T=.T+1
DEFSTR(TSMXP,\<.T>,35,36)		; Max send packet length (inc header)

; Option Variables

.T=.T+1
DEFSTR(TIPDO,\<.T>,5,4)		;TEMP	; IP Data offset, words
DEFSTR(TIPOR,\<.T>,11,6)		; IP Received options, bytes
DEFSTR(TIPOU,\<.T>,17,6)		; IP User options, bytes
DEFSTR(TIOPF,\<.T>,35,18)		; IP User option flags

.T=.T+1
DEFSTR(TTPDO,\<.T>,5,4)		;TEMP	; TCP Data offset, words
DEFSTR(TTPOR,\<.T>,11,6)		; TCP Received options, bytes
DEFSTR(TTPOU,\<.T>,17,6)		; TCP User options, bytes
DEFSTR(TTOPF,\<.T>,35,18)		; TCP User option flags

TCBIO==<.T=.T+1>		;TEMP	; IP Option list (send)
TCBIR==<.T=.T+<MAXIOS+3>/4>		; Last IP Options received
TCBIU==<.T=.T+<MAXIOS+3>/4>		; IP Options from User

TCBTO==<.T=.T+<MAXIOS+3>/4>	;TEMP	; TCP Option list (send)
TCBTR==<.T=.T+<MAXTOS+3>/4>		; Last TCP Options received
TCBTU==<.T=.T+<MAXTOS+3>/4>		; TCP Options from User

.T=.T+<MAXTOS+3>/4
DEFSTR(TERBF,\<.T>,17,18)		; Error/Trace (user) buffer adr
DEFSTR(TERJN,\<.T>,35,18)		; Error/trace (user) JFN

.T=.T+1
DEFSTR(TCTBS,\<.T>,17,18)		; Count of no-buffer errors
DEFSTR(TCTSQ,\<.T>,35,18)		; Count of sequence # pauses

.T=.T+1
DEFSTR(TSCPK,\<.T>,35,36)		; Send current packet

.T=.T+1					; Spare
TCBSIZ==.T+1				; Size of a TCB
	PURGE .T


; The following definition must match that in TTTVDV.MAC

IFNKA <	TTNETW==4 >		; (i.e. TTDEV)
IFKA  <	EXTERN TTNETW >
DEFSTR(PTVT,TTNETW,35,18)	; Holds pointer to TVT's TCB

; Flag bit definitions: (Now in MONSYM)

IFNDEF TCP%ER,<	PRINTX % TCP Buffer header flag bits not defined in MONSYM
TCP%ER==1B0			; ERROR
TCP%LE==1B1			; Local error flag (0 is remote)
TCP%PE==1B2			; Permanent error (0 is temporary)
TCP%EC==37B7			; Error code w/o flags
TCP%DN==1B12			; DONE
TCP%UR==1B15			; URGENT DATA
TCP%EL==1B16	; obsolete	; PUSH
TCP%PU==1B16			; PUSH
TCP%WM==1B17			; WORD MODE
.TCPBF==0			; Buffer Flags
.TCPBA==1			; Buffer data address
.TCPBC==2			; Buffer data count
.TCPBO==3			; Buffer option addresses
 .TCPOW==↑D10			; Buffer option address word count
.TCPBI==4			; Buffer IP info
.TCPBS==5			; Buffer header size
	>


; CHKARG stack parameter block definitions

;		Caller				Callee

;	STACKL <<ARGBLK,CHKADW>,...>
;	CHKADL <<locals>>			CHKADL <<locals>>
;	...code...				...code...
;	CHKADR					CHKADR

DEFINE CHKADL (LOCL)<
IFB  <LOCL>,<	LOCAL <PARAMS>		>
IFNB <LOCL>,<	LOCAL <PARAMS,LOCL>	>
	LALL
DEFINE LH<0(PARAMS)>
DEFINE LP<1(PARAMS)>
DEFINE FH<2(PARAMS)>
DEFINE FP<3(PARAMS)>
DEFINE JCN<4(PARAMS)>
DEFINE WILDOK<5(PARAMS)>
DEFINE FN<6(PARAMS)>
DEFINE ARG1<7(PARAMS)>
DEFINE ARG2<10(PARAMS)>
	SALL
> ; End of DEFINE CHKADL

CHKADW==11

DEFINE CHKADR <
	PURGE LH,LP,FH,FP,JCN,WILDOK,FN,ARG1,ARG2
	RESTORE
> ; End of CHKADR

; BUFFER Structure:

BFRQ==<.B==0>			; BUFFER QUEUE, LH contains flags

BFRSUI==<.B==.B+QSZ>		; BUFFER START USER INFORMATION
; Offsets defined in MONSYM
BFRFLG==BFRSUI+.TCPBF		; BUFFER FLAG WORD
DEFSTR(BURG,BFRFLG,↑L<TCP%UR>,1); BUFFER URGENT
DEFSTR(BEOL,BFRFLG,↑L<TCP%PU>,1); BUFFER END-OF-LETTER
DEFSTR(BWM,BFRFLG,↑L<TCP%WM>,1)	; BUFFER WORD-MODE
BFRDAD==BFRSUI+.TCPBA
DEFSTR(BDADR,BFRDAD,35,36)	; BUFFER DATA ADDRESS
BFRCNT==BFRSUI+.TCPBC
DEFSTR(BCNT,BFRCNT,35,36)	; BUFFER.COUNT
BFROPT==BFRSUI+.TCPBO
;
BFREUI==<.B==BFRSUI+.TCPBS>	; BUFFER END USER INFO

DEFSTR(BHADR,\<.B>,35,36)	; BUFFER HEADER ADDRESS
.B==.B+1
DEFSTR(BICNT,\<.B>,35,36)	; BUFFER INITIAL COUNT
.B==.B+1
DEFSTR(BFRKX,\<.B>,17,18)	; BUFFER.FORKX

DEFSTR(BUPAG,\<.B>,35,18)	; BUFFER.USER PAGE
.B==.B+1
DEFSTR(BBLIP,\<.B>,17,18)	; BUFFER.BYTESLEFTINPAGE
DEFSTR(BMPAG,\<.B>,35,18)	; BUFFER.MONITORPAGE

BFRPTR==<.B==.B+1>
DEFSTR(BPTR,BFRPTR,35,36)	; BUFFER POINTER
  ; Overlays for above:
  DEFSTR(BPTRP,BFRPTR,5,6)	; Size field
  DEFSTR(BPTRS,BFRPTR,11,6)	; Position field
  DEFSTR(BPTRA,BFRPTR,35,18)	; Address field

.B==.B+1
DEFSTR(BTCB,\<.B>,17,18)	; BUFFER.TCB
DEFSTR(BIDX,\<.B>,35,18)	; BUFFER.INDEX
.B==.B+1
DEFSTR(BTS,\<.B>,35,36)		; BUFFER.TIMESTAMP
	BFRSIZ==.B+1
; AC1 Bits for TCP JSYSs (Now in MONSYM)

IFNDEF TCP%JS,<	PRINTX % TCP JSYS flag bits not defined in MONSYM
TCP%JS==1B0	; JCN Supplied
TCP%WT==1B1	; Wait for completion
TCP%FS==1B5	; Force Synchronization (active open)
TCP%PS==1B6	; Persistent open
TCP%ST==1B7	; Return statistics (STAT)
TCP%SY==1B8	; Symbolic name list given (STAT)
TCP%SC==1B8	; Secure connection (OPEN, SEND)
TCP%HP==1B9	; High priority (OPEN, SEND)
TCP%VT==1B10	; TCP Virtual Terminal (OPEN)
TCP%TV==1B11	; TVT Supplied (STAT)
TCP%NT==1B12	; Return AOBJN pointer over TVTs (STAT)
TCP%IX==1B13	; Connection index supplied (STAT)
TCP%NI==1B14	; Return AOBJN pointer over connections (STAT)
TCP%SD==1B15	; Return STAT definitions instead of values (STAT)
TCP%ET==1B16	; ERROR info flag
TCP%PT==1B17	; Packet trace flag
.TCPLH==0	; Connection Local Host (0 is wild)
.TCPLP==1	; Connection Local Port (0 is illegal)
.TCPFH==2	; Connection Foreign Host (0 is wild)
.TCPFP==3	; Connection Foreign Port (0 is wild)
.TCPOP==4	; Connection Option addresses
 .TCPOW==↑D10	; Connection Option address word count
.TCPIP==5	; Connection IP parameters (Flag=3B1, TTL=377B17, TOS=377B35)
.TCPCS==6	; Connection block word size
	>

; Event codes:

E.BIT==200			; ERROR bit
L.BIT==100			; LOCAL condition bit
P.BIT==040			; PERMANENT condition bit

OK==0*E.BIT+0*L.BIT+0*P.BIT	; General success code
XFT==0*L.BIT+0*P.BIT		; Temporary Foreign condition
XFP==0*L.BIT+1*P.BIT		; Permanent Foreign condition
XLP==1*L.BIT+1*P.BIT		; Permanent Local condition
EFT==1*E.BIT+0*L.BIT+0*P.BIT	; Temporary Foreign Error
EFP==1*E.BIT+0*L.BIT+1*P.BIT	; Permanent Foreign Error
ELT==1*E.BIT+1*L.BIT+0*P.BIT	; Temporary Local Error
ELP==1*E.BIT+1*L.BIT+1*P.BIT	; Permanent Local Error

; Other codes:

IGN==100		; Packet is to be ignored
DUP==10			; Packet is a duplicate (in TCPIP)
ERR==1			; Packet is in error (in TCPIP)
; Process block

PRCQ==0			; (Ext) ptr to input queue head (TCBs, etc)
PRCLCK==1		; Lock
.F==PRCLCK+LOCKSZ
PRCROU==.F		; (Ext) address of routine
PRCWAK==.F+1		; -1 or TODCLK of wakeup
PRCQOF==.F+2		; TCB,,m	Pointer to queue in TCB
PRCWOF==.F+3		; TCB,,n	Pointer to wakeup in TCB
PRCSGT==.F+4		; TODCLK of most recent signal
PRCRNC==.F+5		; Pointer to run counter	xxRNCT
PRCTMR==.F+6		; Pointer to timer		xxUSE
	PROCSZ==.F+7	; Size of a process block


; Macro which expands into code to cause a process to run after
; a specified delay.  The interesting case is 0 delay in which
; the routine may be called directly, without the overhead of locking
; and unlocking the process Q twice, and locking the TCB again etc.

DEFINE $SIGNL(TPROC,DELTA,%TAGQ,%TAGX)<
	XMOVEI T1,TPROC		; Process to signal
IFNKA <
  IFE DELTA,<
	MOVE T3,TODCLK		; Now
	SKIPL T2,PRCWAK(T1)	; If no wakeup set, NOW is ok
	 CAMLE T2,T3		; If past due, queue
	  SKIPLE NSKED		; NOW is ok unless NOSKED
	   JRST %TAGQ		; No.  Get in Q for FIFO behavior
	PUSH P,PROC		; Do it NOW
	MOVEM T3,PRCSGT(T1)	; TODCLK of most recent SIGNAL
	CALL TCPTSK		; Call the task
	POP P,PROC		; Restore our ID as running process
	JRST %TAGX		; All done
%TAGQ:	>>	;IFE DELTA, IFNKA

; Avoid stack overflow on KA, always queue
	MOVX T2,DELTA		; Number of milliseconds
	CALL SIGNAL
IFNKA <
  IFE DELTA,<
%TAGX:  >>

> ; end DEFINE $